#!/usr/bin/env python
# encoding: utf-8

"""
Cookie-based session storage class.
Stores the data into the cookie value.
"""

try:
    import cPickle as pickle
except ImportError:
    import pickle
import base64
import logging

from spyro.session.storage.base import BaseStorage
from spyro.config.register import Register
from spyro.internal.utils.exceptions import SessionException

log = logging.getLogger(__name__)

class Storage(BaseStorage):
    """Stores the data serialized on the client side
    as a cookie value.
    No need to check for the expiration time, when the
    cookie will be expired it won't be sent back.
    """
    
    def __init__(self, request, response):
        self.request = request
        self.response = response
        
        cookie_name = Register.sessions['cookie']
        self._data = self.request.cookie(cookie_name, dict())
        
        if not isinstance(self._data, dict):
            self._data = base64.b64decode(self._data.encode())
            self._data = pickle.loads(self._data)

    def __setitem__(self, key, value):
        """Stores the pair `key':`value'.
        """
        
        self._data[key] = value
        
        serialized_data = pickle.dumps(self._data)
        serialized_data = base64.b64encode(serialized_data)
        
        # let's store the data immediatly
        cookie_name = Register.sessions['cookie']
        cookie_expiry = int(Register.sessions['expiration'])
        self.response.set_cookie(cookie_name, serialized_data.decode(), 
                                 life_secs=cookie_expiry, httponly=True)
    
    def __getitem__(self, key):
        """Returns the value assigned to `key' or `default' otherwise.
        """
        
        try:
            return self._data[key]
        except KeyError:
            raise SessionException("Unsetted key: %r" % key)
    
    def __delitem__(self, key):
        """Deletes the "key" from the current session data.
        """

        try:
            del self._data[key]
        except KeyError:
            raise SessionException("Deleting an unsetted key: %r" % key)
    
    def destroy(self):
        """Destroys the session cookie and cleans the current data.
        """
        
        cookie_name = Register.sessions['cookie']
        self.response.delete_cookie(cookie_name)
        self._data = None

    def __contains__(self, key):
        """Implement the support for the "in" operator on the session class.
        That's the prefered way to know if a key was set.
        """
        
        return key in self._data
